package com.opengate.base.result;

import com.opengate.base.constants.AppConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

/**
 * @author 曳戈泰尔
 * @version 1.0
 * @description 返回结果
 * @date 2023/4/26 5:46 PM
 */
@Data
@Accessors(chain = true)
@Schema(description = "返回结果")
public class Result<T> {

    /** 状态 */
    @Schema(description = "状态", required = true)
    private Status status;

    /** 状态码 */
    @Schema(description = "状态码", required = true)
    private int code;

    /** 消息 */
    @Schema(description = "消息", required = true)
    private String message;

    /** 请求ID */
    @Schema(description = "请求ID", required = true)
    private String requestId;

    /** 数据 */
    @Schema(description = "数据", required = true)
    private T data;

    /**
     * 创建返回结果
     *
     * @param status 状态
     * @param code 状态码
     * @param message 消息
     * @param data 数据
     * @param <T> 数据
     * @return 返回结果
     */
    private static <T> Result<T> create(Status status, int code, String message, T data) {
        return new Result<T>()
                .setStatus(status)
                .setCode(code)
                .setMessage(message)
                // 从MDC中获取请求ID，唯一标识一次请求
                .setRequestId(MDC.get(AppConstants.HEADER_RID_NAME))
                .setData(data);
    }

    public static <T> Result<T> success(T data) {
        return create(Status.SUCCESS, Status.SUCCESS.ordinal(), StringUtils.EMPTY, data);
    }

    public static <T> Result<T> success() {
        return create(Status.SUCCESS, Status.SUCCESS.ordinal(), StringUtils.EMPTY, null);
    }

    public static <T> Result<T> fail(Status status, int code, String message) {
        return create(status, code, message, null);
    }

    public static <T> Result<T> fail(Status status) {
        return fail(status, status.ordinal(), StringUtils.EMPTY);
    }

    public static <T> Result<T> fail(String message) {
        return fail(Status.EXCEPTION, Status.EXCEPTION.ordinal(), message);
    }

    public static <T> Result<T> fail(Status status, String message) {
        return fail(status, status.ordinal(), message);
    }

    public static <T> Result<T> fail(int code, String message) {
        return fail(Status.EXCEPTION, code, message);
    }

    public static <T> Result<T> fail() {
        return fail(Status.EXCEPTION, Status.EXCEPTION.ordinal(), StringUtils.EMPTY);
    }

    /** 状态 枚举 */
    public enum Status {
        // 成功
        SUCCESS,
        // 失败请求
        BAD_REQUEST,
        // 未认证
        UNAUTHORIZED,
        // 验证异常
        VALIDATION_EXCEPTION,
        // 异常
        EXCEPTION,
        // 错误的凭证
        WRONG_CREDENTIALS,
        // 通道拒绝
        ACCESS_DENIED
    }
}
